package pl.prv.polanie.client.widgets.schedule;

import pl.prv.polanie.client.Planner;
import pl.prv.polanie.client.dialogs.CreateSubjectEventDialog;
import pl.prv.polanie.client.dto.CSGroupDTO;
import pl.prv.polanie.client.dto.CSSubgroupDTO;
import pl.prv.polanie.client.dto.CSSubjectEventDTO;
import pl.prv.polanie.client.dto.CSVSubjectEventDTO;
import pl.prv.polanie.client.model.Cache;
import pl.prv.polanie.client.model.CacheService;
import pl.prv.polanie.client.model.ContextSettings;
import pl.prv.polanie.client.model.ServiceHolder;
import pl.prv.polanie.client.model.ViewDataProvider;
import pl.prv.polanie.client.panels.SchedulesList;
import pl.prv.polanie.client.widgets.layout.tooltip.ToolTip;
import pl.prv.polanie.client.widgets.schedule.widgets.DraggableElement;
import pl.prv.polanie.client.widgets.schedule.widgets.DraggableZone;
import pl.prv.polanie.client.widgets.util.GUIUtil;
import pl.prv.polanie.client.widgets.utils.Borders;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventPreview;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.MouseListenerAdapter;
import com.google.gwt.user.client.ui.Widget;

public class SubjectEvent extends DraggableElement implements Comparable<SubjectEvent> {
	
	private static final String STYLE_EVENT = "my-Event";
	private static final String STYLE_EVENT_BOTTOM_LEFT = "my-Event-bottomLeft";
	private static final String STYLE_EVENT_TOP_RIGHT = "my-Event-topRight";

	private static final String STYLE_EVENT_BACKGROUND_IMAGE = "my-Event-backgroundImage";
	
	private static final String STYLE_EVENT_HEADER = "my-Event-header";
	private static final String STYLE_EVENT_HANDLER = "my-Event-handler";
	
	private static final String STYLE_EVENT_PROPERTY = "my-Event-property";
	private static final String STYLE_EVENT_PROPERTY_RIGHT = "my-Event-property-right";
	private static final String STYLE_EVENT_DETAILS = "my-Event-details";
	
	private static final String STYLE_EVENT_REMOVE_ICON = "my-Event-removeIcon";
	private static final String STYLE_EVENT_EDIT_ICON = "my-Event-editIcon";

	
	
	
	/** html with triangle/rectangular image */
	private final Image backgroundImage = new Image();
	
	//user can catch for it and start dragging
	private final HTML handlerHTML = new HTML("");

	/** Indicates if SE has been at least one time attached to DOM. */
	private boolean wasAttached = false;
	
	/**
	 * wskazuje czy zajecia odbywaja sie:
	 * 	co tydzien = 0
	 * 	w tygodnie parzyste = 1
	 *  w tygodnie nieparzyste = 2
	 */
	
	private boolean draggingInProgress = false;
	private AbsolutePanel mainAP = new AbsolutePanel();
	

	private Image editIconImage;
	private Image removeIconImage;

	private static final String editSubjectEventImageURL = "images/subjectEvent_edit.png";
	private static final String removeSubjectEventImageURL = "images/customTabPanel_close.png";

	
	private CSSubjectEventDTO csSubjectEventDTO = null;
	private CSVSubjectEventDTO csvSubjectEventDTO = null;
	
	private HTML eventProperty1HTML;  
	private HTML eventProperty2HTML;  
	private HTML eventProperty3HTML;
	
	
	/**
	 * EP nasluchujacy eventow myszy przy najechaniu na subjectEvent.
	 */
	private final EventPreview whileDraggingOverEP = new EventPreview() {
		public boolean onEventPreview(Event event) {
			
			switch (DOM.eventGetType(event)) {

			case Event.ONMOUSEMOVE:
				if (!ScheduleUtil.eventOverWiget(handlerHTML, event)) {
					//WYJEZDZAMY KURSOREM POZA SE
					Planner.hideToolTip();
					DOM.removeEventPreview(whileDraggingOverEP);
					hideEditIcons();
					DraggableZone dz = getParentDraggableZone();
					if (dz != null) {
						dz.getParentSchedule().removeHighlightingFromSubjectEvent();
					}
				} else {
					//NAD KONTROLKA
					//nie jest wyswietlony && nie jest draggowany
					if (!Planner.isToolTipDisplayed() && !draggingInProgress ) {
						ToolTip tip = new ToolTip(csvSubjectEventDTO);
						Planner.displayToolTip(tip, DOM.eventGetClientX(event) + 10, DOM.eventGetClientY(event) + 10);	
					} else {
						Planner.setToolTipPosition(DOM.eventGetClientX(event) + 10, DOM.eventGetClientY(event) + 10);
					}
				}
				break;
			case Event.ONMOUSEDOWN:
				
				if (ContextSettings.isAdminUserSignedIn()) {
					
					//kod uruchamiany w momencie klikniecia na SE
					if (ScheduleUtil.eventOverWiget(removeIconImage, event)) {
						//jezeli klikamy na kontrolce usuwajacej SE ze Schedule, to nie rozpoczynamy draggowania
						break;
					} else {
						if (event.getCtrlKey()) {
//							Planner.log("SubjectEvent.whileDragginOverEP.onEventPreview(): " + "CTRL");
							
							CSSubjectEventDTO newCSSE = new CSSubjectEventDTO();
							newCSSE.setCalendarDayID(csSubjectEventDTO.getCalendarDayID());
							newCSSE.setDuration(new Integer(csSubjectEventDTO.getDuration()));
							newCSSE.setEventSort(csSubjectEventDTO.getEventSort());
							newCSSE.setLecturerID(csSubjectEventDTO.getLecturerID());
							newCSSE.setRoomID(csSubjectEventDTO.getRoomID());
							newCSSE.setStartTime(new Integer(csSubjectEventDTO.getStartTime()));
							newCSSE.setSubgroupID(csSubjectEventDTO.getSubgroupID());
							newCSSE.setSubjectID(csSubjectEventDTO.getSubjectID());
							
							CSVSubjectEventDTO newCSVSE = ViewDataProvider.getCSVSubjectEvent(newCSSE);
							
							SubjectEvent newSE = new SubjectEvent(newCSSE, newCSVSE);
							Day d = getParentDay();
							getParentDraggableZone().getParentSchedule().addSubjectEventToDay(d, newSE);
							newSE.startDragging(event);
							
						} else {
							startDragging(event);
						}
						break;
					}
				}

			case Event.ONMOUSEUP:
				if (draggingInProgress) {
					draggingInProgress = false;
					runOnMouseUpWhileDragging(event);
				}
			}
			
			
			return true;
		}


	};


	/**
	 * @param event
	 */
	private void startDragging(Event event) {
		Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
		//WLACZENIE TRYBU EDYCJI SE
		
		parentSchedule.showHeaderLabelHints();
		parentSchedule.showSubjectEventEditionWidget(SubjectEvent.this);
		
		int y = ScheduleUtil.getEventYOverWidget(handlerHTML, event);
		setDraggingOn(y);
		draggingInProgress = true;
		
		removeHighlighting();
//				Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
		parentSchedule.removeHighlightingFromSubjectEvent();
		parentSchedule.setSelectedSubjectEventByID(csSubjectEventDTO.getId());
		parentSchedule.setSelectedSubjectEventInTableByID(csSubjectEventDTO.getId());
	}
	
	
	private MouseListener mouseListenerAdapter = new MouseListenerAdapter(){
//		@Override
		public void onMouseEnter(Widget sender) {
//			Planner.log("SubjectEvent.CALY CZAS WCHODZEEEE: " + "" + draggingInProgress);
			super.onMouseEnter(sender);
			getParentDraggableZone().getParentSchedule().highlightSubjectEventInTableByID(csSubjectEventDTO.getId());
			getParentDraggableZone().getParentSchedule().highlightSubjectEventByID(csSubjectEventDTO.getId());
			
			if (ContextSettings.isAdminUserSignedIn()) {
				showEditIcons();
			}
			
			DOM.addEventPreview(whileDraggingOverEP);
		}
	};
	

	
	/**
	 * Metoda uruchamiana w momencie rozpoczynania draggowania SubjectEventa.
	 */
	@Override
	protected void runOnStartDragging() {
		super.runOnStartDragging();
		
		Planner.hideToolTip();
		
		//loadLecturerPreferences();
		//loadSubjectEventHintsForRoom();
		//loadSubjectEventHintsForLecturer();
		
		//zajete
//		parentSchedule.showLocationsForSubjectEvents();
	}

	
	
	
	/**
	 * @param parentSchedule
	 */
	private void loadLecturerPreferences() {
		Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
		
		//preferencje lecturera
		Long lecturerID = new Long(csSubjectEventDTO.getLecturerID());
		Long semesterID = new Long(parentSchedule.getFilterPropertySemesterID());
		SchedulesList.downloadCSLecturerPreferences(parentSchedule, lecturerID, semesterID);
	}
	
	private void hideLecturerPreferencesInSchedule() {
		Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
		parentSchedule.hideLecturerPreferences();
	}
	
	private void toggleLecturerPreferencesInSchedule() {
		Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
		if (parentSchedule.isAreShownLecturerPreferences()) {
			//chowamy lp
			hideLecturerPreferencesInSchedule();
		} else {
			//wczytujemy
			loadLecturerPreferences();
		}
	}


	public void loadSubjectEventHintsForLecturer() {
//		Planner.log("SubjectEvent.loadSubjectEventHintsForLecturer: " + "");
		final Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
		
		if (!parentSchedule.isAreShownSubjectEventsHintsForLecturer()) {
//			Long semesterID = new Long(parentSchedule.getFilterPropertySemesterID());
			
			//lecturer
			Long lecturerID = new Long(csSubjectEventDTO.getLecturerID());
			SchedulesList.downloadSubjectEventsForLecturer(csSubjectEventDTO, parentSchedule, lecturerID);
		}
	}
	

	public void loadSubjectEventLecturerPreferences() {
		
		Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
		//preferencje lecturera
		if (!parentSchedule.isAreShownLecturerPreferences()) {
			Long lecturerID = new Long(csSubjectEventDTO.getLecturerID());
			Long semesterID = new Long(parentSchedule.getFilterPropertySemesterID());
			SchedulesList.downloadCSLecturerPreferences(parentSchedule, lecturerID, semesterID);
		}
	}
	
	public void hideSubjectEventLecturerPreferences() {
		//TODO tutaj zmienic
		Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
		if (parentSchedule.isAreShownLecturerPreferences()) {
			//chowamy sehintsy
			parentSchedule.hideLecturerPreferences();
		}
	}


	
	
	
	public void toggleSubjectEventHintsForLecturer() {
		Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
		if (parentSchedule.isAreShownSubjectEventsHintsForLecturer()) {
			//chowamy sehintsy
			hideSubjectEventHintsForLecturer();
		} else {
			//wczytujemy
			loadSubjectEventHintsForLecturer();
		}
	}
	

	public void hideSubjectEventHintsForLecturer() {
		Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
		if (parentSchedule.isAreShownSubjectEventsHintsForLecturer()) {
			//chowamy sehintsy
			parentSchedule.hideSubjectEventsHints(SubjectEventHint.HINT_SORT__LECTURER);
		}
	}
	
	
	

	
	//ROOM HINTS
	public void loadSubjectEventHintsForRoom() {
		final Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
		Long semesterID = new Long(parentSchedule.getFilterPropertySemesterID());
		
		//room
		Long roomID = new Long(csSubjectEventDTO.getRoomID());
		SchedulesList.downloadSubjectEventsForRoom(csSubjectEventDTO, parentSchedule, roomID);
	}
	
	public void hideSubjectEventHintsForRoom() {
		Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
		if (parentSchedule.isAreShownSubjectEventsHintsForRoom()) {
			parentSchedule.hideSubjectEventsHints(SubjectEventHint.HINT_SORT__ROOM);
		}
	}
	
	

	
	private void toggleSubjectEventHintsForRoom() {
		Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
		if (parentSchedule.isAreShownSubjectEventsHintsForRoom()) {
			//chowamy sehintsy
			hideSubjectEventHintsForRoom();
		} else {
			//wczytujemy
			loadSubjectEventHintsForRoom();
		}
	}
	
	
	
	


	public SubjectEvent(CSSubjectEventDTO dto, CSVSubjectEventDTO csvDto) {
		this.csSubjectEventDTO = dto;
		//this.y = ScheduleUtil.convertFromStartTimeToPixels(dto.getStartTime().intValue());
//		this.y = (int)((dto.getStartTime().intValue() - 420) / (60f) *36);
		
		
		
		
		CSVSubjectEventDTO csvSE;
		if (csvDto != null) {
			csvSE = csvDto;
		} else {
			csvSE = ViewDataProvider.getCSVSubjectEvent(dto);	
		}
		this.csvSubjectEventDTO = csvSE;
		setupEventPropertiesHTML(csvSE);
		setupBackgroundImageHTML();
		setupHandlerHTML();
		setupMainAP();
		
		initWidget(mainAP);
		
		int h = ScheduleUtil.convertFromDurationToPixels(dto.getDuration().intValue(), CacheService.isFullTimeSemesterSelected());
		this.setHeight(h+"px");

		
		
		
		//ustawienie wlascwiej szerokosci
		
		int w = ContextSettings.getDayWidthInPixels();
		
		
		CSSubgroupDTO subgroupDTO = Cache.getCSSubgroupDTOByID(dto.getSubgroupID());
		
		if (subgroupDTO != null) {
			CSGroupDTO groupDTO = Cache.getCSGroupDTOByID(subgroupDTO.getGroupID());
			
			int subgroupSN = subgroupDTO.getStudentsNumber().intValue();
			int groupSN = groupDTO.getStudentsNumber().intValue();
			
			w = (int)((float)subgroupSN/(float)groupSN * w);
			
		}
//		Planner.log("SubjectEvent.SubjectEvent: " + "SETUJE WIDTH");
		this.setWidth(w+"px");
		//////////////////////////////////
		
		setStyleName(STYLE_EVENT);
		//Borders.addRedDashedBorders(mainAP);
	}


	protected void onAttach() {
		// TODO Auto-generated method stub
		super.onAttach();
		if (!wasAttached) {
			wasAttached = true;
			
//			if (subjectEventDTO != null) {
			if (csSubjectEventDTO != null) {
				int eventSort = csSubjectEventDTO.getEventSort();
				if (eventSort == 0) {
					setAll();
				} else if (eventSort == 1) {
					//parzysty
					setBottomLeft();
				} else if (eventSort == 2) {
					//nieparzysty
					setTopRight();
				}
			}
		}
		//attached = true;
	}
	

	private void setupEventPropertiesHTML(CSVSubjectEventDTO csvSE) {
//		eventProperty1HTML = new HTML("[" + csvSE.getId() + "]" + csvSE.getSubjectNameSymbol());
		eventProperty1HTML = new HTML(csvSE.getSubjectNameSymbol());
		eventProperty1HTML.setStyleName(STYLE_EVENT_PROPERTY);
		eventProperty2HTML = new HTML(csvSE.getSubjectTypeInitial() + " " + csvSE.getRoom());
		eventProperty2HTML.setStyleName(STYLE_EVENT_PROPERTY);
		
		String lecturerSurname = csvSE.getLecturerSurname(); 
		if (lecturerSurname.equals("-no lecturer-")) {
			lecturerSurname = "";
		}
		eventProperty3HTML = new HTML(lecturerSurname);
		eventProperty3HTML.setStyleName(STYLE_EVENT_PROPERTY);
		
//		headerHTML.setWidth(200+"px");
//		headerHTML.setHeight(20+"px");
//		eventDetailsHTML = new HTML("Ale je asda sd as das sd das<br>xx<br>z");
//		eventDetailsHTML.setStyleName(STYLE_EVENT_DETAILS);
	}
	
	private void setupBackgroundImageHTML() {
		backgroundImage.setStyleName(STYLE_EVENT_BACKGROUND_IMAGE);
		backgroundImage.setWidth(200+"px");
		backgroundImage.setHeight(54+"px");
	}
	
	
	private void setupHandlerHTML() {
		handlerHTML.setStyleName(STYLE_EVENT_HANDLER);
		handlerHTML.setWidth(200+"px");
		handlerHTML.setHeight(54+"px");
		Planner.disableSelection(handlerHTML.getElement());
		handlerHTML.addMouseListener(mouseListenerAdapter);
//		handlerHTML.addClickListener(clickListenerAdapter);
//		handlerHTML.sinkEvents(com.google.gwt.user.client.Event.ONMOUSEUP);
//		DOM.setEventListener(handlerHTML.getElement(), new EventListener() {
//			public void onBrowserEvent(com.google.gwt.user.client.Event event) {
//				Planner.log("DOM.onMouseUp");
//				
//
//				
//			}
//		});
//		handlerHTML.addMouseListener(new MouseListenerAdapter(){
//			public void onMouseDown(Widget sender, int x, int y) {
////				Window.alert("aa");
//				setDraggingOn(y);
//			}
//		});
//		headerHTML.sinkEvents(com.google.gwt.user.client.Event.MOUSEEVENTS);		
//		DOM.setEventListener(headerHTML.getElement(), new EventListener() {
//			public void onBrowserEvent(com.google.gwt.user.client.Event event) {
//				// TODO Auto-generated method stub
//				Window.alert("a");
//			}
//		});
	}
	
	private void setAll() {
		if (csSubjectEventDTO != null) {
			csSubjectEventDTO.setEventSort(0);
		}
		removeStyleName(STYLE_EVENT_TOP_RIGHT);
		removeStyleName(STYLE_EVENT_BOTTOM_LEFT);
		
		backgroundImage.setUrl("./images-schedule/all.png");
		
		mainAP.setWidgetPosition(eventProperty1HTML, 0, 0);
		mainAP.setWidgetPosition(eventProperty2HTML, 0, 10);
		mainAP.setWidgetPosition(eventProperty3HTML, 0, 20);
	}
	
	private void setTopRight() {
		if (csSubjectEventDTO != null) {
			csSubjectEventDTO.setEventSort(2);
		}
		removeStyleName(STYLE_EVENT_BOTTOM_LEFT);
		addStyleName(STYLE_EVENT_TOP_RIGHT);
		
		backgroundImage.setUrl("./images-schedule/top_right_200_54.png");
		
		mainAP.setWidgetPosition(eventProperty1HTML, mainAP.getOffsetWidth()-eventProperty1HTML.getOffsetWidth()-2, 0);
		mainAP.setWidgetPosition(eventProperty2HTML, mainAP.getOffsetWidth()-eventProperty2HTML.getOffsetWidth()-2, 10);
		mainAP.setWidgetPosition(eventProperty3HTML, mainAP.getOffsetWidth()-eventProperty3HTML.getOffsetWidth()-2, 20);
		
		
		
//		eventProperty1HTML.addStyleName(STYLE_EVENT_PROPERTY_RIGHT);
//		DOM.setElementProperty(eventProperty1HTML.getElement(), "bottom", "0px");
//		eventProperty2HTML.addStyleName(STYLE_EVENT_PROPERTY_RIGHT);
//		DOM.setElementProperty(eventProperty2HTML.getElement(), "bottom", "10px");
//		eventProperty3HTML.addStyleName(STYLE_EVENT_PROPERTY_RIGHT);
//		DOM.setElementProperty(eventProperty3HTML.getElement(), "bottom", "20px");
	}
	
	private void setBottomLeft() {
		if (csSubjectEventDTO != null) {
			csSubjectEventDTO.setEventSort(1);
		}
		removeStyleName(STYLE_EVENT_TOP_RIGHT);
		addStyleName(STYLE_EVENT_BOTTOM_LEFT);
		
		backgroundImage.setUrl("./images-schedule/bottom_left_200_54.png");
		
		mainAP.setWidgetPosition(eventProperty1HTML, 0, mainAP.getOffsetHeight()-30);
		mainAP.setWidgetPosition(eventProperty2HTML, 0, mainAP.getOffsetHeight()-20);
		mainAP.setWidgetPosition(eventProperty3HTML, 0, mainAP.getOffsetHeight()-10);
		
//		eventProperty1HTML.addStyleName(STYLE_EVENT_PROPERTY_RIGHT);
//		DOM.setElementProperty(eventProperty1HTML.getElement(), "bottom", "0px");
//		eventProperty2HTML.addStyleName(STYLE_EVENT_PROPERTY_RIGHT);
//		DOM.setElementProperty(eventProperty2HTML.getElement(), "bottom", "10px");
//		eventProperty3HTML.addStyleName(STYLE_EVENT_PROPERTY_RIGHT);
//		DOM.setElementProperty(eventProperty3HTML.getElement(), "bottom", "20px");
	}
	
	
	/** 
	 * Metoda uruchamiana podczas draggowania w momencie nacisniecia na klawisz.
	 */
	protected void onKeyDown(char c, boolean ctrlPressed) {
		super.onKeyDown(c, ctrlPressed);
		
		DraggableZone dz = getParentDraggableZone();
		Schedule schedule = dz.getParentSchedule();
		
		if (c == '1') {
			schedule.toggleLocationsForSubjectEvents();
		} else if (c == '2') {
//			loadLecturerPreferences();
			toggleLecturerPreferencesInSchedule();
//			schedule.to
		} else if (c == '3') {
			//3 - pokaz/schowaj subjectEventy dla lecturera
			toggleSubjectEventHintsForLecturer();
		} else if (c == '4' ) {
			//
			toggleSubjectEventHintsForRoom();
		} else if (!ctrlPressed){
			if (csSubjectEventDTO != null) {
				if (csSubjectEventDTO.getEventSort() == 0) {
					setBottomLeft();
				} else if (csSubjectEventDTO.getEventSort() == 1) {
					setTopRight();
				} else if (csSubjectEventDTO.getEventSort() == 2) {
					setAll();
				}
			}
		}

	}
	
	protected void onMouseMove(int x, int y) {
		super.onMouseMove(x, y);
		draggingInProgress = false;
	}
	
	private void setupMainAP() {
		GUIUtil.prepareToResize(mainAP);
		mainAP.setWidth("200px");
		mainAP.setHeight("54px");
		GUIUtil.restoreAfterResize(mainAP);
		
		mainAP.add(eventProperty1HTML,-1,-1);
		mainAP.add(eventProperty2HTML,-1,-1);
		mainAP.add(eventProperty3HTML,-1,-1);
		
		//mainAP.add(eventDetailsHTML);
		mainAP.add(backgroundImage, 0, 0);
		mainAP.add(handlerHTML, 0, 0);
	}

//	public int getY() {
//		return y;
//	}
//
//	public void setY(int y) {
//		this.y = y;
//	}
	
	
//	@Override
	protected void runOnDrop(int left, int top) {
		super.runOnDrop(left, top);
		draggingInProgress = false;
		getParentDraggableZone().getParentSchedule().hideLecturerPreferences();
		getParentDraggableZone().getParentSchedule().hideSubjectEventsHints();
		saveSubjectEventAfterDragging();
		getParentDraggableZone().getParentSchedule().hideLocationsForSubjectEvents();
	}
	
	/**
	 * Zapisuje subjectEvent. Metoda uzywana po przeciagnieciu subjectEventa.
	 */
	private void saveSubjectEventAfterDragging() {
		//final SubjectEventDTO se = subjectEventDTO;
		
		final CSSubjectEventDTO se = csSubjectEventDTO;

		
		if (isInSubjectEventsCart()) {
			se.setCalendarDayID(-1);
		} else {
			//mapowanie polozenia w kontrolce draggable zone (zawartej w dniu)
			//na start time i duration
			
			//startTime
			DraggableZone parentDZ = getParentDraggableZone();
			int top = parentDZ.getWidgetTop(this);
			
//			double startTime = top * 60/(double)36 + 420;
			double startTime2 = ScheduleUtil.convertFromPixelsToStartTime(top, CacheService.isFullTimeSemesterSelected());
			
//			Planner.log("SubjectEvent.saveSubjectEvent wyliczono startTime: " + startTime2);
			se.setStartTime(new Integer((int) startTime2));
			
			//calendarDayID
			Day day = parentDZ.getParentDay();
			se.setCalendarDayID(day.getCalendarDayDTO().getId());
		}
		
//		se.setSubject((SubjectDTO)subjectLB.getSelectedObject());
//		se.setLecturer((LecturerDTO)lecturerLB.getSelectedObject());
//		se.setSubgroup((SubgroupDTO)subgroupLB.getSelectedObject());
//		se.setRoom((RoomDTO)roomLB.getSelectedObject());
//		se.setCalendarDay((CalendarDayDTO)calendarDayLB.getSelectedObject());
//		se.setStartTime(new Integer(startTimeTB.getText()));
//		se.setDuration(new Integer(durationTB.getText()));
//
//		
//		
//		dto.get
		
		
		//ustawienie atrybutow w dto
		
		AsyncCallback<Long> callback = new AsyncCallback<Long>(){
			public void onFailure(Throwable caught) {
				Planner.log("SubjectEvent.saveSubjectEvent ONFAILURE blad przy probie zapisu");
			}
			public void onSuccess(Long res) {
				Planner.log("SubjectEvent.saveSubjectEvent ONSUCCESS");
				getParentDay().fixSubjectEventsPositions();
				if (!isSubjectEventSaved()) {
					Planner.log("SubjectEvent.onSuccess: SAVE " + "zapisuje do dto id: " + res.longValue());
					csSubjectEventDTO.setId(res.longValue());
					getParentDraggableZone().getParentSchedule().saveOrUpdateSubjectEventInTable(se);
					getParentDraggableZone().getParentSchedule().setSelectedSubjectEventInTableByID(res.longValue());
				} else {
					getParentDraggableZone().getParentSchedule().saveOrUpdateSubjectEventInTable(se);
				}
				
				
				Cache.saveOrUpdateCSSubjectEvent(se);
				SchedulesList.generateReports();
			}
		};
		ServiceHolder.get().saveCSSubjectEvent(se, callback);

	}
	
	/**
	 * Zapisuje SE po usunieciu z kontrolki podzialu.
	 */
	private void saveSubjectEventAfterRemoving() {
		//final SubjectEventDTO se = subjectEventDTO;
		
		final CSSubjectEventDTO se = csSubjectEventDTO;
		final long seID = se.getId();
		se.setCalendarDayID(-1);
		
		AsyncCallback callback = new AsyncCallback(){
			
			public void onFailure(Throwable caught) {
				Planner.log("SubjectEvent.saveSubjectEvent ONFAILURE blad przy probie zapisu");
			}
			
			public void onSuccess(Object result) {
				getParentDraggableZone().getParentSchedule().saveOrUpdateSubjectEventInTable(se);
				Planner.log("SubjectEvent.saveSubjectEvent ONSUCCESS zapisano SE, id=" + seID);

				getParentDraggableZone().remove(SubjectEvent.this);
				
				Cache.saveOrUpdateCSSubjectEvent(se);
				SchedulesList.generateReports();
			}
			
		};
		
		ServiceHolder.get().saveCSSubjectEvent(se, callback);
	}
	
	
	public void highlightSubjectEvent() {
		Borders.addGrayDashedBorders(mainAP);
	}
	
	public void selectSubjectEvent() {
		Borders.removeAllBorders(mainAP, Borders.BORDERS_GRAY);
		Borders.addBlueDashedBorders(mainAP);
	}

	
	public void removeHighlighting() {
//		Planner.log("SubjectEvent.removeHighlighting: " + "probuje usunac SZARE ramki");
		Borders.removeAllBorders(mainAP, Borders.BORDERS_GRAY);
	}
	
	public void removeSelection() {
		Borders.removeAllBorders(mainAP, Borders.BORDERS_BLUE);
	}
	
	
	/**
	 * Wskazuje czy subjectEvent jest podpiety do koszyka z nieprzydzielonymi subjectEventami, <br>
	 * czy tez moze do dnia w kalendarzu.
	 * @return
	 */
	private boolean isInSubjectEventsCart() {
		return ((DraggableZone)getParent()).isSubjectEevntsCart();
	}
	
//	private DraggableZone getParentDraggableZone() {
//		return (DraggableZone)getParent();
//	}
	
	
	
//	@Override
	public void setHeight(String height) {
		super.setHeight(height);
		backgroundImage.setHeight(height);
		handlerHTML.setHeight(height);
	}
	
	public void setWidth(String width) {
		super.setWidth(width);
		backgroundImage.setWidth(width);
		handlerHTML.setWidth(width);
		
		if (csSubjectEventDTO != null && csSubjectEventDTO.getEventSort() == 2) {
			setTopRight();
		}
	}

	public CSSubjectEventDTO getSubjectEventDTO() {
		return csSubjectEventDTO;
	}


	
	/**
	 * Pokazuje kontrolki na lecturerPreferences sluzace do zmiany rozmiaru/usuwania.
	 */
	private void showEditIcons() {
		
		if (removeIconImage == null) {
			removeIconImage = new Image(removeSubjectEventImageURL){
				@Override
				public void onBrowserEvent(Event event) {
					super.onBrowserEvent(event);
					
					switch (DOM.eventGetType(event)) {
						case Event.ONMOUSEOUT:
							if (!ScheduleUtil.eventOverWiget(SubjectEvent.this, event)) {
								Planner.hideToolTip();
								//hideCloseIcon();
							}
							break;
					}
				}
			};
			removeIconImage.setStyleName(STYLE_EVENT_REMOVE_ICON);
			removeIconImage.setWidth(14+"px");
			removeIconImage.setHeight(20 + "px");
			removeIconImage.addClickListener(new ClickListener() {
				public void onClick(Widget sender) {
					Planner.log("removeIconHTML.onClick: " + "");
					saveSubjectEventAfterRemoving();
//					deleteSubjectEventFromSchedule();
				}
			});
			mainAP.add(removeIconImage);
		}
		
		if (editIconImage == null) {
			editIconImage = new Image(editSubjectEventImageURL){
				@Override
				public void onBrowserEvent(Event event) {
					super.onBrowserEvent(event);
					
					switch (DOM.eventGetType(event)) {
						case Event.ONMOUSEOUT:
							if (!ScheduleUtil.eventOverWiget(SubjectEvent.this, event)) {
								Planner.hideToolTip();
								//hideCloseIcon();
							}
							break;
					}
				}
			};
			editIconImage.setStyleName(STYLE_EVENT_EDIT_ICON);
			editIconImage.setWidth(14 + "px");
			editIconImage.setHeight(20 + "px");
			editIconImage.addClickListener(new ClickListener() {
				public void onClick(Widget sender) {
					Planner.log("editIconHTML.onClick: " + "");
					
					Schedule parentSchedule = getParentDraggableZone().getParentSchedule();
					
					CreateSubjectEventDialog csed = new CreateSubjectEventDialog(parentSchedule, null, csSubjectEventDTO); 
					csed.center();
					
//					saveSubjectEventAfterRemoving();
//					deleteSubjectEventFromSchedule();
				}
			});
			mainAP.add(editIconImage);
		}
	}
	
	
	/**
	 * Usuwa kontrolki na subjectEvent sluzace do zmiany rozmiaru/usuwania.
	 */
	private void hideEditIcons() {
		
		if (removeIconImage != null) {
			mainAP.remove(removeIconImage);
			removeIconImage = null;
		}
		
		if (editIconImage != null) {
			mainAP.remove(editIconImage);
			editIconImage = null;
		}		

		
		Schedule parentSchedule = getParentSchedule();
		if (parentSchedule != null) {
			parentSchedule.removeHighlightingFromSubjectEvent();
		} 
	}
	
	private Schedule getParentSchedule() {
		DraggableZone dz = getParentDraggableZone();
	
		if (dz != null) {
			return dz.getParentSchedule();
		}
		
		return null;
	}

	
	/**
	 * Usuwa subjectEventz z konkretnego dnia w podziale. (ustawia calendarDayID = -1)
	 */
	private void deleteSubjectEventFromSchedule() {
		final CSSubjectEventDTO csSE = csSubjectEventDTO;
		final long seID = csSE.getId();
		csSE.setCalendarDayID(-1);
		
		Planner.log("SubjectEvent.deleteSubjectEvent()");
		AsyncCallback callback = new AsyncCallback(){
			public void onFailure(Throwable caught) {
				Planner.log("SubjectEvent.deleteSubjectEvent ONFAILURE blad przy probie zapisu");
			}
			public void onSuccess(Object result) {
				
				//LecturerPreferences.this.csPreferenceDTO.setId(lpID);
				Planner.log("SubjectEvent.deleteSubjectEvent ONSUCCESS usunieto id " + seID);
			}
		};
		ServiceHolder.get().saveCSSubjectEvent(csSE, callback);
	}

	
	
	/**
	 * Idzie w gore drzewa DOM i zwraca obiekt Day, jesli istnieje. Jesli nie, zwraca null.
	 * @return
	 */
	public Day getParentDay() {
		Widget w = getParent();
		
		while (w != null) {
			if (w instanceof Day) {
				return (Day)w;
			}
			w = w.getParent();
		}
		
		return null;
	}
	
	
	/**
	 * Przywraca szerkosc wynikajaca z liczebnosci subgroup w stosunku do liczebnosci group. 
	 */
	public void restorePrimalWidth() {
		
		//ustawienie wlasciwej szerokosci
		CSSubgroupDTO subgroupDTO = Cache.getCSSubgroupDTOByID(getSubjectEventDTO().getSubgroupID()); 
		CSGroupDTO groupDTO = Cache.getCSGroupDTOByID(subgroupDTO.getGroupID());
		
		int subgroupSN = subgroupDTO.getStudentsNumber().intValue();
		int groupSN = groupDTO.getStudentsNumber().intValue();
		
		int w = (int)((float)subgroupSN/(float)groupSN * ContextSettings.getDayWidthInPixels());
		
		setWidth(w + "px");
	}

	
	
	public int compareTo(SubjectEvent se) {
//	    final int BEFORE = -1;
	    final int EQUAL = 0;
//	    final int AFTER = 1;
	    
		//this optimization is usually worthwhile, and can
		//always be added
		if ( this == se ) return EQUAL;
		
		//primitive numbers follow this form
		return this.getSubjectEventDTO().getStartTime().compareTo(se.getSubjectEventDTO().getStartTime());
//		if (this.getSubjectEventDTO().getStartTime().intValue() < se.getSubjectEventDTO().getStartTime().intValue()) return BEFORE;
//		if (this.getSubjectEventDTO().getStartTime().intValue() > se.getSubjectEventDTO().getStartTime().intValue()) return AFTER;
//		if (this.getSubjectEventDTO().getStartTime().intValue() == se.getSubjectEventDTO().getStartTime().intValue()) return EQUAL;
//
//
//		return EQUAL;
	}
	
	/**
	 * Wskazuje, czy subject event ma przypisane id w obiekcie csSE.
	 * @return
	 */
	public boolean isSubjectEventSaved() {
		return csSubjectEventDTO.getId() != 0;
	}

	
	public int getTopInDraggableZone() {
		DraggableZone parentDZ = getParentDraggableZone();
		return parentDZ.getWidgetTop(this);
	}
	
	public int getLeftInDraggableZone() {
		DraggableZone parentDZ = getParentDraggableZone();
		return parentDZ.getWidgetLeft(this);
	}

	public void setLeftInDraggableZone(int left) {
		DraggableZone parentDZ = getParentDraggableZone();
		parentDZ.setWidgetPosition(this, left, getTopInDraggableZone());
	}
	
	public int getWidth () {
		return mainAP.getOffsetWidth();
	}
	
}
